package ldh.maker.code;

import javafx.scene.control.TreeItem;
import ldh.database.Column;
import ldh.database.Table;
import ldh.maker.database.TableInfo;
import ldh.maker.freemaker.*;
import ldh.maker.util.DbInfoFactory;
import ldh.maker.util.EnumFactory;
import ldh.maker.util.FileUtil;
import ldh.maker.util.FreeMakerUtil;
import ldh.maker.vo.DBConnectionData;
import ldh.maker.vo.SettingData;
import ldh.maker.vo.TreeNode;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import static java.lang.System.arraycopy;

/**
 * Created by ldh on 2017/4/6.
 */
public class VertxCreateCode extends WebCreateCode {

    public VertxCreateCode(SettingData data, TreeItem<TreeNode> treeItem, String dbName, Table table) {
        super(data, treeItem, dbName, table);
        add("/vertx/head.ftl", "head.ftl", "template", "common");
        add("/vertx/left.ftl", "left.ftl", "template", "common");
        add("/vertx/jspMain.ftl", "main.ftl", "template");
    }

    @Override
    public void create() {
        if (data == null) return;
        if (!table.isCreate()) return;

        if (table.getPrimaryKey() != null && !table.getPrimaryKey().isComposite()) {
            Column c = table.getPrimaryKey().getColumns().iterator().next();
        }

        KeyMaker keyMaker = null;
        if (table.getPrimaryKey() == null || table.getPrimaryKey().isComposite()) {
            return;
        }

        for (Column column : table.getColumnList()) {
            String keyId = treeItem.getParent().getValue().getId() + "_" + dbName + "_" + table.getName() + "_" + column.getName();
            EnumStatusMaker enumStatusMaker = EnumFactory.getInstance().get(keyId);
            if (enumStatusMaker != null) {
//                String p = createPath(enumStatusMaker.getPack());
//                enumStatusMaker.outPath(p).make();
                column.setJavaType(enumStatusMaker.getSimpleName());
            }
        }

        if (keyMaker != null) return;

        if (!table.isMiddle()) {
            buildService();
        }

        createOther();
    }

    private void buildService() {
        String beanPackage = data.getDaoPackageProperty();
        String outPath = createPath(beanPackage);
        new ObjectMaker()
                .beanPackage(beanPackage)
                .author(data.getAuthorProperty())
                .description(table.getComment())
                .fileName(table.getJavaName() + "Dao.java")
                .ftl("vertx/BeanDao.ftl")
                .outPath(outPath)
                .table(table)
                .put("projectPackage", getProjectRootPackage(beanPackage))
                .make();

        beanPackage = data.getServicePackageProperty();
        String projectPackage = getProjectRootPackage(beanPackage);
        outPath = createPath(beanPackage);
        new ObjectMaker()
                .beanPackage(beanPackage)
                .author(data.getAuthorProperty())
                .description(table.getComment())
                .table(table)
                .fileName(table.getJavaName() + "Service.java")
                .ftl("vertx/BeanService.ftl")
                .put("projectPackage", projectPackage)
                .put("daoPackage", data.getDaoPackageProperty())
                .outPath(outPath)
                .make();

        new ObjectMaker()
                .beanPackage(beanPackage)
                .author(data.getAuthorProperty())
                .table(table)
                .fileName("JdbcService.java")
                .ftl("vertx/JdbcService.ftl")
                .outPath(outPath)
                .make();

        new ObjectMaker()
                .beanPackage(beanPackage)
                .author(data.getAuthorProperty())
                .table(table)
                .fileName("JdbcAble.java")
                .ftl("vertx/JdbcAble.ftl")
                .outPath(outPath)
                .make();

        projectPackage = getProjectRootPackage(data.getControllerPackageProperty());
        beanPackage = projectPackage + ".verticle.router";
        outPath = createPath(beanPackage);
        new ObjectMaker()
                .fileName(table.getJavaName() + "Router.java")
                .table(table)
                .beanPackage(beanPackage)
                .author(data.getAuthorProperty())
                .ftl("vertx/router.ftl")
                .outPath(outPath)
                .put("projectPackage", projectPackage)
                .put("servicePackage", data.getServicePackageProperty())
                .make();

        beanPackage = projectPackage + ".verticle";
        outPath = createPath(beanPackage);
        new ObjectMaker()
                .fileName("MainHttpRouter.java")
                .beanPackage(beanPackage)
                .author(data.getAuthorProperty())
                .table(table)
                .ftl("vertx/mainRouter.ftl")
                .outPath(outPath)
                .put("projectPackage", projectPackage)
                .make();

        new ObjectMaker()
                .fileName("ParentSyncVerticle.java")
                .beanPackage(beanPackage)
                .author(data.getAuthorProperty())
                .table(table)
                .ftl("vertx/ParentSyncVerticle.ftl")
                .outPath(outPath)
                .put("projectPackage", projectPackage)
                .make();

        outPath = createPath(projectPackage);
        String db = treeItem.getValue().getData().toString();
        TableInfo tableInfo = DbInfoFactory.getInstance().get(treeItem.getValue().getParent().getId() + "_" + db);

        new ObjectMaker()
                .fileName("VertxApplication.java")
                .beanPackage(projectPackage)
                .author(data.getAuthorProperty())
                .table(table)
                .ftl("vertx/VertxApplication.ftl")
                .outPath(outPath)
                .put("projectPackage", projectPackage)
                .put("tableInfo", tableInfo)
                .make();
    }

    private void buildUtil(Table table) {
        String beanPackage = getProjectRootPackage(data.getPojoPackageProperty()) + ".util";
        String outPath = createPath(beanPackage);;
        new ObjectMaker()
                .beanPackage(beanPackage)
                .author(data.getAuthorProperty())
                .table(table)
                .fileName("BeanUtil.java")
                .ftl("vertx/BeanUtil.ftl")
                .outPath(outPath)
                .make();

        new ObjectMaker()
                .beanPackage(beanPackage)
                .author(data.getAuthorProperty())
                .table(table)
                .fileName("VertxUtil.java")
                .ftl("vertx/VertxUtil.ftl")
                .outPath(outPath)
                .make();

        new ObjectMaker()
                .beanPackage(beanPackage)
                .author(data.getAuthorProperty())
                .table(table)
                .fileName("JsonObjectUtil.java")
                .ftl("vertx/JsonObjectUtil.ftl")
                .outPath(outPath)
                .make();

        String author = data.getAuthorProperty();
        TreeNode treeNode = treeItem.getValue().getParent();
        DBConnectionData data = (DBConnectionData) treeNode.getData();
        new ObjectMaker()
                .beanPackage(beanPackage)
                .author(author)
                .table(table)
                .fileName("DbUtil.java")
                .ftl("vertx/DbUtil.ftl")
                .put("jdbc_ip", data.getIpProperty())
                .put("jdbc_port", data.getPortProperty())
                .put("jdbc_userName", data.getUserNameProperty())
                .put("jdbc_password", data.getPasswordProperty())
                .put("jdbc_dbName", dbName)
                .outPath(outPath)
                .make();
    }

    @Override
    protected void createOther(){
        if (resourceMap != null) {
            for (Map.Entry<String, String[]> entry : resourceMap.entrySet()) {
                String[] dirs = new String[entry.getValue().length-1];
                arraycopy(entry.getValue(), 1, dirs, 0, dirs.length);
                String path = createJspPath(dirs);
                String db = treeItem.getValue().getData().toString();
                TableInfo tableInfo = DbInfoFactory.getInstance().get(treeItem.getValue().getParent().getId() + "_" + db);
                new JspMainMaker()
                        .tableInfo(tableInfo)
                        .ftl(entry.getKey())
                        .outPath(path)
                        .fileName(entry.getValue()[0])
                        .make();
            }
        }

        String db = treeItem.getValue().getData().toString();
        TableInfo tableInfo = DbInfoFactory.getInstance().get(treeItem.getValue().getParent().getId() + "_" + db);
        String t = FreeMakerUtil.firstLower(table.getJavaName());
        new JspMaker()
                .tableInfo(tableInfo)
                .table(table)
                .outPath(createFtlPath(FreeMakerUtil.javaName(table.getName())))
                .ftl("/vertx/jspList.ftl")
                .fileName(t + "List.ftl")
                .make();

        new JspMaker()
                .tableInfo(tableInfo)
                .table(table)
                .outPath(createFtlPath(FreeMakerUtil.javaName(table.getName())))
                .ftl("/vertx/jspView.ftl")
                .fileName(t + "View.ftl")
                .make();

        new JspMaker()
                .tableInfo(tableInfo)
                .table(table)
                .outPath(createFtlPath(FreeMakerUtil.javaName(table.getName())))
                .ftl("/vertx/jspEdit.ftl")
                .fileName(t + "Edit.ftl")
                .make();

        List<String> dirs = new ArrayList<>(Arrays.asList("code", root, this.getProjectName(), "src", "main", "resources"));
        try {
            if (!isCreate) return;
            buildPomXmlMaker("");
            buildUtil(table);

            copyResources("common/js", dirs, "resource", "common", "js");
            copyResources("ftl/vertx/macro", dirs, "template", "macro");
            copyResources("common/bootstrap", dirs, "resource", "common");
            copyResources("frame", dirs, "resource", "frame");
            isCreate = false;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void buildPomXmlMaker(String path) {
        String projectRootPackage = getProjectRootPackage(data.getPojoPackageProperty());
        String resourcePath = createPomPath();
        new PomXmlMaker()
                .projectRootPackage(projectRootPackage)
                .projectName(this.getProjectName())
                .ftl("/vertx/pom.ftl")
                .outPath(resourcePath)
                .make();
    }

    @Override
    protected String createFtlPath(String dir) {
        String path = FileUtil.getSourceRoot();
        List<String> dirs = new ArrayList<>(Arrays.asList("code", root, getProjectName(), "src", "main", "resources", "template", dir));
        path = makePath(path, dirs);
        return path;
    }

    protected void buildApplicationPropertiesMaker() {
        String projectRootPackage = getProjectRootPackage(data.getPojoPackageProperty());
        String resourcePath = createResourcePath();
        TreeNode treeNode = treeItem.getValue().getParent();
        DBConnectionData data = (DBConnectionData) treeNode.getData();
        new ApplicationPropertiesMaker()
                .projectRootPackage(projectRootPackage)
                .dBConnectionData(data)
                .ftl("freemarker/applicationProperties.ftl")
                .dbName(dbName)
                .outPath(resourcePath)
                .make();
    }

    protected String createJspPath(String... dirs) {
        String path = FileUtil.getSourceRoot();
        List<String> dirst = new ArrayList<>(Arrays.asList("code", root, getProjectName(), "src", "main", "resources"));
        for (String d : dirs) {
            dirst.add(d.toString());
        }
        path = makePath(path, dirst);
        return path;
    }

    protected String createJsPath() {
        String path = FileUtil.getSourceRoot();
        List<String> dirs = new ArrayList<>(Arrays.asList("code", root, getProjectName(), "src", "main", "resources"));
        path = makePath(path, dirs);
        return path;
    }

    protected String createJspPath() {
        String path = FileUtil.getSourceRoot();
        List<String> dirs = new ArrayList<>(Arrays.asList("code", root, getProjectName(), "src", "main", "resources", "templates", "ftl"));
        path = makePath(path, dirs);
        return path;
    }

    public String getProjectName() {
        return data.getProjectNameProperty();
    }
}
